# -*- coding: utf-8 -*-
import KBEngine
import IKernel
import MsgDef
import ErrorCodeDef
import ConstDef
import NameModDef
import time
import random
import LogDef
import ValChangedDef
import json
import weakref
import xml.dom.minidom

from KBEDebug import *

class ContainerHandler:
	def __init__(self):
		pass

	def init(self, isReload):
		self.propSyncFlagsCfg = {}

		IKernel.Instance().registerFunc("ContainerHandler.HB_delaySyncData", self.HB_delaySyncData)

		if KBEngine.component == "baseapp":
			IKernel.Instance().registerFunc("ContainerHandler.onClientEnabled", self.onClientEnabled)
			IKernel.Instance().addEventCallback("Account", "onClientEnabled", "ContainerHandler.onClientEnabled")

		IKernel.Instance().registerFunc("ContainerHandler.onEntityInit", self.onEntityInit)
		IKernel.Instance().addEventCallback("Common", "init", "ContainerHandler.onEntityInit")

		self.loadRes()

	def end(self):
		pass

	def loadRes(self):
		self.propSyncFlagsCfg = {}

		path = KBEngine.getResFullPath("cfg/prop_sync_flags.xml")
		#打开xml文档
		dom = xml.dom.minidom.parse(path)
		#得到文档元素对象
		root = dom.documentElement

		propEle = root.getElementsByTagName("property")
		for prop in propEle :
			entityName = prop.getAttribute("EntityName")
			propName = prop.getAttribute("ContainerPropName");
			flag = prop.getAttribute("Flag");

			entityFlags = self.propSyncFlagsCfg.get(entityName)
			if entityFlags == None:
				self.propSyncFlagsCfg[entityName] = {}
				entityFlags = self.propSyncFlagsCfg.get(entityName)
			entityFlags[propName] = flag

	def onClientEnabled(self, eventType, eventName, senderEntityID, receiverEntityID, args):
		self.installContainerChangeEvent(receiverEntityID)

	def onEntityInit(self, eventType, eventName, senderEntityID, receiverEntityID, args):
		if KBEngine.component == "baseapp" and eventType == "Account":
			# 带客户端的实体，需要在 onClientEnabled 里面处理
			return
		self.installContainerChangeEvent(receiverEntityID)

	def setupOwner(self, container, owner, ownSelfKey):
		from FUSE_FIELD import FUSE_FIELD
		for k, v in container.items():
			if isinstance(v, FUSE_FIELD):
				self.setupOwner(v, container, k)

		container.owner = weakref.proxy(owner)
		container.ownSelfKey = ownSelfKey

	def installContainerChangeEvent(self, entityID):
		entity = KBEngine.entities.get(entityID)
		# 增加延迟同步数据变量
		if hasattr(entity, "delaySyncData") == False:
			entity.delaySyncData = []

		from FUSE_FIELD import FUSE_FIELD
		from FUSE_FIELD_NEST import FUSE_FIELD_NEST
		for k, v in entity.__dict__.items():
			if isinstance(v, FUSE_FIELD) == False \
				and isinstance(v, FUSE_FIELD_NEST) == False :
				continue

			self.setupOwner(v, entity, k)
			self.syncData(entity, k, ValChangedDef.DATA_ADD, v)

	def syncData(self, entity, propName, changeType, changeVals):
		entityFlagsCfg = self.propSyncFlagsCfg.get(entity.getScriptName())
		if entityFlagsCfg == None or entityFlagsCfg.get(propName) == None :
			return

		entity.delaySyncData.append([propName, changeType, changeVals])

		entity.delHeartbeat("ContainerHandler.HB_delaySyncData")
		entity.addHeartbeat("ContainerHandler.HB_delaySyncData", 1, 1)

	def HB_delaySyncData(self, entityID, curCount, interval):
		entity = KBEngine.entities.get(entityID)
		for propName, changeType, changeVals in entity.delaySyncData:
			entityFlagsCfg = self.propSyncFlagsCfg.get(entity.getScriptName())
			if entityFlagsCfg == None or entityFlagsCfg.get(propName) == None :
				continue
			flag = entityFlagsCfg.get(propName)

			msg = []
			msg.append(MsgDef.SVR2CLIENT_CONTAINER_SYNC_MSG)
			msg.append(propName)
			msg.append(changeType)
			msg.append(self.getDictNotifyData(changeVals))

			if flag == "OTHER_CLIENT" :
				if KBEngine.component == "cellapp":
					IKernel.Instance().sendOtherClientsMsgInView(entity.id, msg)
			elif flag == "OWN_CLIENT" or flag == "BASE_AND_CLIENT":
				IKernel.Instance().sendClientMsg(entity.id, msg)
			elif flag == "CELL_PUBLIC" or flag == "ALL_CLIENTS":
				if KBEngine.component == "cellapp":
					IKernel.Instance().sendAllClientsMsgInView(entity.id, msg)

		entity.delaySyncData = []

	def getDictNotifyData(sef, changeVals):
		if len(changeVals) == 0:
			from FUSE_FIELD import FUSE_FIELD
			from FUSE_FIELD_NEST import FUSE_FIELD_NEST
			if type(changeVals) == FUSE_FIELD:
				return "null=>0()null=>0"
			elif type(changeVals) == FUSE_FIELD_NEST:
				return "null=>0()null=>0()null=>0"
			return ""
		"""
		map<int, map<int, int>> = {
			1:{
				11:111,
				12:122,
				13:133,
				14:144,
				15:155,
				16:166
			},
			2:{
				21:211,
				22:222,
				23:233,
				24:244,
				25:255,
				26:266
			},
		}
		1=>1()11=>1()111=>1
		{}1=>1()12=>1()122=>1
		{}1=>1()13=>1()133=>1
		{}1=>1()14=>1()144=>1
		{}1=>1()15=>1()155=>1
		{}1=>1()16=>1()166=>1
		"""

		notifyData = ""

		for kL1, vL1 in changeVals.items():
			if isinstance(vL1, dict) == False:
				vL1NumType = 0
				if vL1 == None:
					vL1 = "null"
				else:
					IKernel.Instance().getSimpleNumType(vL1)

				if notifyData != "":
					notifyData = notifyData + "{}"
				notifyData = notifyData + "{}=>{}(){}=>{}".format(kL1, IKernel.Instance().getSimpleNumType(kL1), vL1, vL1NumType)
				continue

			for kL2, vL2 in vL1.items():
				if isinstance(vL2, dict) == False:
					vL2NumType = 0
					if vL2 == None:
						vL2 = "null"
					else:
						IKernel.Instance().getSimpleNumType(vL2)

					if notifyData != "":
						notifyData = notifyData + "{}"
					notifyData = notifyData+ "{}=>{}(){}=>{}(){}=>{}".format(kL1, IKernel.Instance().getSimpleNumType(kL1),
						kL2, IKernel.Instance().getSimpleNumType(kL2),
						vL2, vL2NumType)
					continue

				for kL3, vL3 in vL2.items():
					# 3层的dict还没有用到，用到的时候在加
					assert(False)
					if notifyData != "":
						notifyData = notifyData + "{}"

		return notifyData